home *** CD-ROM | disk | FTP | other *** search
/ Language/OS - Multiplatform Resource Library / LANGUAGE OS.iso / gnu / glibc108.gz / glibc108 / glibc-1.08.1 / stdio / fwrite.c < prev    next >
C/C++ Source or Header  |  1993-04-21  |  5KB  |  192 lines

  1. /* Copyright (C) 1991, 1992, 1993 Free Software Foundation, Inc.
  2. This file is part of the GNU C Library.
  3.  
  4. The GNU C Library is free software; you can redistribute it and/or
  5. modify it under the terms of the GNU Library General Public License as
  6. published by the Free Software Foundation; either version 2 of the
  7. License, or (at your option) any later version.
  8.  
  9. The GNU C Library is distributed in the hope that it will be useful,
  10. but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  12. Library General Public License for more details.
  13.  
  14. You should have received a copy of the GNU Library General Public
  15. License along with the GNU C Library; see the file COPYING.LIB.  If
  16. not, write to the Free Software Foundation, Inc., 675 Mass Ave,
  17. Cambridge, MA 02139, USA.  */
  18.  
  19. #include <ansidecl.h>
  20. #include <errno.h>
  21. #include <stdio.h>
  22. #include <string.h>
  23.  
  24.  
  25. /* Write NMEMB chunks of SIZE bytes each from PTR onto STREAM.  */
  26. size_t
  27. DEFUN(fwrite, (ptr, size, nmemb, stream),
  28.       CONST PTR ptr AND size_t size AND
  29.       size_t nmemb AND register FILE *stream)
  30. {
  31.   register CONST unsigned char *p = (CONST unsigned char *) ptr;
  32.   register size_t to_write = size * nmemb;
  33.   register size_t written = 0;
  34.   int newlinep;
  35.   size_t buffer_space;
  36.   char default_func;
  37.  
  38.   if (!__validfp (stream) || !stream->__mode.__write)
  39.     {
  40.       errno = EINVAL;
  41.       return 0;
  42.     }
  43.  
  44.   if (ferror (stream))
  45.     return 0;
  46.   if (p == NULL || to_write == 0)
  47.     return 0;
  48.  
  49.   if (!stream->__seen || stream->__put_limit == stream->__buffer)
  50.     {
  51.       /* This stream has never been seen before.
  52.      Calling __flshfp will give it a buffer
  53.      and I/O functions if it needs them.  */
  54.       if (__flshfp (stream, *p++) == EOF)
  55.     return 0;
  56.       if (--to_write == 0)
  57.     return 1;
  58.       else
  59.     ++written;
  60.     }
  61.  
  62.   default_func
  63.     = stream->__room_funcs.__output == __default_room_functions.__output;
  64.  
  65.   {
  66.     int save = errno;
  67.  
  68.     if (__stdio_check_offset (stream) == EOF && errno != ESPIPE)
  69.       {
  70.     stream->__error = 1;
  71.     goto done;
  72.       }
  73.  
  74.     errno = save;
  75.   }
  76.  
  77.   if (stream->__buffer == NULL && default_func &&
  78.       stream->__offset == stream->__target)
  79.   write_through:
  80.     /* This is an unbuffered stream using the standard output
  81.        buffer-flushing function, so we just do a straight write.  */
  82.     {
  83.       int count = (stream->__io_funcs.__write == NULL ? to_write :
  84.            (*stream->__io_funcs.__write) (stream->__cookie,
  85.                           (CONST char *) p,
  86.                           to_write));
  87.       if (count > 0)
  88.     {
  89.       written += count;
  90.       if (stream->__offset != -1)
  91.         {
  92.           stream->__offset += count;
  93.           stream->__target = stream->__offset;
  94.         }
  95.       to_write -= count;
  96.       p += count;
  97.     }
  98.       else
  99.     stream->__error = 1;
  100.       goto done;
  101.     }
  102.  
  103.   /* We ignore the end pointer here since we want to find out how much space
  104.      is really in the buffer, even for a line-buffered stream.  */
  105.   buffer_space = stream->__bufsize - (stream->__bufp - stream->__buffer);
  106.  
  107.   newlinep = (stream->__linebuf &&
  108.           memchr ((CONST PTR) p, '\n', to_write) != NULL);
  109.  
  110.   if (newlinep && stream->__bufp == stream->__buffer &&
  111.       stream->__offset == stream->__target)
  112.     /* The buffer's empty, and we want to write our data
  113.        out soon anyway, so just write it straight out.  */
  114.     goto write_through;
  115.  
  116.   if (stream->__bufsize == 0 && !default_func)
  117.     {
  118.       /* No buffer, and a special function.
  119.      We can't do much better than putc.  */
  120.       while (to_write-- > 0)
  121.     {
  122.       if (__flshfp (stream, *p++) == EOF)
  123.         break;
  124.       else
  125.         ++written;
  126.     }
  127.     }
  128.   else if (!default_func || buffer_space >= to_write)
  129.   fill_buffer:
  130.     /* There is enough room in the buffer for everything we
  131.        want to write or the user has specified his own output
  132.        buffer-flushing/expanding function.  */
  133.     while (to_write > 0)
  134.       {
  135.     register size_t n = to_write;
  136.  
  137.     if (n > buffer_space)
  138.       n = buffer_space;
  139.  
  140.     buffer_space -= n;
  141.  
  142.     written += n;
  143.     to_write -= n;
  144.  
  145.     if (n < 20)
  146.       while (n-- > 0)
  147.         *stream->__bufp++ = *p++;
  148.     else
  149.       {
  150.         memcpy ((PTR) stream->__bufp, (PTR) p, n);
  151.         stream->__bufp += n;
  152.         p += n;
  153.       }
  154.  
  155.     if (buffer_space == 0 || (to_write == 0 && newlinep))
  156.       {
  157.         /* We've filled the buffer, so flush it.  */
  158.         if (fflush (stream) == EOF)
  159.           break;
  160.       }
  161.       }
  162.   else
  163.     {
  164.       /* It won't all fit in the buffer.  */
  165.  
  166.       if (stream->__bufp != stream->__buffer)
  167.     {
  168.       /* There are characters in the buffer.  Flush them.  */
  169.       if (__flshfp (stream, EOF) == EOF)
  170.         goto done;
  171.     }
  172.  
  173.       /* The buffer has been flushed.
  174.      Now either fill it or write directly.  */
  175.  
  176.       buffer_space = stream->__bufsize - (stream->__bufp - stream->__buffer);
  177.  
  178.       if (stream->__offset == stream->__target &&
  179.       (buffer_space < to_write || newlinep))
  180.     /* What we have to write is bigger than the buffer,
  181.        or it contains a newline and we're line-buffered,
  182.        so write it out.  */
  183.     goto write_through;
  184.       else
  185.     /* It will fit in the buffer.  */
  186.     goto fill_buffer;
  187.     }
  188.  
  189.  done:;
  190.   return (size_t) written / size;
  191. }
  192.